#include "CapBinDataReader.h"
#include "OCMain/zip/BZip2.h"

namespace OCPP {
namespace Volume {

	CapBinDataReader::CapBinDataReader(std::ifstream& ifs)
		:ifsStream(ifs)
	{
		readHeader();
	}

	void CapBinDataReader::readHeader()
	{
		ifsStream.read((char*)&header, sizeof(CapHeader));
		if (ifsStream.gcount() != sizeof(CapHeader))
		{
			hasError = true;
			return;
		} 
		if (String(header.label) != "MOC")
		{
			hasError = true;
			return;
		}
	}

	GridDataValuePtr CapBinDataReader::read(GridData& gridData, const VolumeOptions& options)
	{
		GridDataValuePtr gridDataValuePtr = std::make_shared<GridDataValue>();

		const auto& extent = gridData.extent;
		int dimX = extent.dimX;
		int dimY = extent.dimY;
		size_t dimXY = dimX * dimY;

		String block;
		block.resize(header.blockLen);

		ifsStream.read((char*)block.data(), block.size());
		if (header.Compress == 1)
		{
			String unzipBlock;
			unzipBlock.resize(header.unzipBytes);
			BZip2::decpressBZ2(block, unzipBlock);
			block = unzipBlock;
		}

		if (dimXY * sizeof(uint16) != block.size())
		{
			return nullptr;
		}

		Int16Vector data;
		data.resize(dimXY);
		memcpy((char*)&data[0], (char*)block.data(), block.size());

		auto& vecData = gridDataValuePtr->_vecFloat;
		vecData.resize(dimXY);

		float scale = header.scale;
		float maxValue = 0.0;
		for (auto r = 0; r < dimY; r++)
		{
			for (auto c = 0; c < dimX; c++)
			{
				auto i0 = (dimY - r - 1) * dimX + c;
				auto i1 = r * dimX + c;
				float value = data[i0] / scale;
				if (maxValue < value) maxValue = value;
				vecData[i1] = value;
			}
		}


		return gridDataValuePtr;
	}
}}